#pragma once
#include<iostream>
#include"common.hpp"
#include"InetAddr.hpp"
#include"log.hpp"
#include<cstring>
using namespace Inet;
using namespace LogMudule;
const static int  gdefaultsockfd=-1;
const static uint16_t gdefalutport=8080;
class UdpServer
{
  public:
    UdpServer(uint16_t port=gdefalutport):_sockfd(gdefaultsockfd),_addr(port),_isrunning(false)
    {}
    ~UdpServer()
    {
      if(_sockfd>gdefaultsockfd)
        close(_sockfd);
    }
    void InitUdpServer()
    {
      //1.创建套接字 socket
      _sockfd = ::socket(AF_INET,SOCK_DGRAM,0);
      if(_sockfd<0)
      {
        LOG(LogLevel::FATAL)<<"socket:"<<strerror(errno);
        Die(SOCKET_ERR);
      }
      LOG(LogLevel::INFO)<<"socket success sockfd:"<<_sockfd;
      //2.将套接字与内核进程进行绑定 bind
      int n = ::bind(_sockfd,_addr.NetAddr(),_addr.NetAddrLen());
      if(n<0)
      {
        LOG(LogLevel::FATAL)<<"bind:"<<strerror(errno);
        Die(BIND_ERR);
      }
      LOG(LogLevel::INFO)<<"bind success ";
    }
    //初始化服务器 
    void Start()
    {
      _isrunning = true;
      while(true)
      {
        char buff[1024];
        //输出型参数 存放客户端的sockaddr_in结构
        struct sockaddr_in peer;
        socklen_t len = sizeof(peer);
        //从 UDP 套接字接收数据，并获取发送方的地址信息
        ssize_t n = recvfrom(_sockfd,buff,sizeof(buff)-1,0,CONV(&peer),&len);
        if(n>0)
        {
          InetAdrr cli(peer);
          buff[n]=0;
          std::string clientinfo = cli.IP()+":"+std::to_string(cli.Port())+"#"+buff;
          LOG(LogLevel::DEBUG)<<buff;
          
          std::string echo_string = "echo# ";
          echo_string+=buff;
          sendto(_sockfd,echo_string.c_str(),echo_string.size(),0,CONV(&peer),sizeof(peer));
        }
      }
      _isrunning=false;
    }
  private:
    int _sockfd;
    InetAdrr _addr;
    bool _isrunning;
};